/**
 * @file PatientResource.java
 * @author ApertureScience
 */
package aperturescience.resources;
import java.io.IOException;

import org.json.JSONException;
import org.restlet.ext.json.JsonRepresentation;
import org.restlet.representation.Representation;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.Put;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;

import aperturescience.types.JSONMessageResponse;
import aperturescience.types.JSONPatient;
import aperturescience.wargames.WarGamesApplication;

/**
 * This class defines all the HTTP request handlers regarding individual patients.
 */
public class PatientResource extends ServerResource {
	// DATA FIELDS
	protected JSONPatient patient;			// The underlying Patient object.
	protected String patientId = null;	// The sequence of characters that identifies the resource.

	/**
	 * Gets the predefined patientId from the URI
	 */
	@Override
	protected void doInit() throws ResourceException
	{
		// Get the "patientId" attribute value taken from the URI template /patients/{patientId}.
		this.patientId = (String)getRequest().getAttributes().get("patientId");
	}
	
	/**
	 * Handles GET requests.  Retrieves a Patient from the database at the specified URI
	 *
	 * @returns a JSON representation of the requested resource, if it exists;
	 * 			otherwise, returns a JSONMessageResponse with details.
	 * @see aperturescience.types.JSONMessageResponse
	 */
	@Get("JSON")
	public JsonRepresentation getPatient() {
		DatabaseResource db = new DatabaseResource(WarGamesApplication.couchdburl, WarGamesApplication.databasename);
		try {
			patient = db.getPatient(patientId);
			if(patient == null) {
				return JSONMessageResponse.generateMessageRep("500", "?");
			}
			return patient.getJsonRepresentation();
		} catch(ResourceException e) {
			return JSONMessageResponse.generateMessageRep("404", "Patient[" + patientId + "] not found.");
			
		}
	}
	
	/**
	 * Handles PUT requests; First tries to create a patient at {patientId}; 
	 * if there already exists an entry, update the existing entry with the data
	 * given. 
	 *
	 * @param entity	a representation of the resource to be updated
	 * @returns JSONMessageResponse
	 */
	@Put
	public JsonRepresentation putPatient(Representation entity) {
		//create is primary, update is secondary
		DatabaseResource db = new DatabaseResource(
				WarGamesApplication.couchdburl,
				WarGamesApplication.databasename);
		JSONPatient patient = null;
		
		try {
			patient = new JSONPatient(entity);
		} catch (JSONException e) {
			return JSONMessageResponse.generateMessageRep(400, "Invalid input to create patient.");
		} catch (IOException e) {
			return JSONMessageResponse.generateMessageRep(500, "Communication error");
		}
		
		try {
			if (db.createPatient(patient, patientId))
				return JSONMessageResponse.generateMessageRep(201, patientId);
			else
				return JSONMessageResponse.generateMessageRep(500, "Patient not created");
		} catch (ResourceException e)	{
			//if we decide to ONLY [CREATE] on PUT, do not comment next line, otherwise, it will bounce down to update.
			//return JSONMessageResponse.generateMessageRep(409, "Patient already exists");
		}
		try {
			if (db.updatePatient(patient, patientId))
				return JSONMessageResponse.generateMessageRep(200, patientId);
			else
				return JSONMessageResponse.generateMessageRep(500, "Patient not updated");
		} catch (ResourceException e) {
			return JSONMessageResponse.generateMessageRep(500, "Unknown failure...");
		}
	}
    
	/**
	 * Handles POST requests; Updates a Patient resource in the database at {patientId}.
	 * If no entry exists, it attempts to create one.
	 *
	 * @param entity A representation of the patient to be updated.
	 * @returns JSONMessageResponse with details.
	 * @see aperturescience.types.JSONMessageResponse
	 */
	@Post
	public JsonRepresentation postPatient(Representation entity) {
		//update is primary, create is secondary
		DatabaseResource db = new DatabaseResource(
				WarGamesApplication.couchdburl,
				WarGamesApplication.databasename);
		JSONPatient patient = null;
		
		try {
			patient = new JSONPatient(entity);
		} catch (JSONException e) {
			return JSONMessageResponse.generateMessageRep(400, "Invalid patient data.");
		} catch (IOException e) {
			return JSONMessageResponse.generateMessageRep(500, "Communication error");
		}
		
		if( db.getPatient(patientId) != null )
			if (db.updatePatient(patient, patientId))
				return JSONMessageResponse.generateMessageRep(200, patientId);
			else
				return JSONMessageResponse.generateMessageRep(500, "Patient not updated");
		//else return JSONMessageResponse.generateMessageRep(404, "Patient does not exist");
		else
			if (db.createPatient(patient, patientId))
				return JSONMessageResponse.generateMessageRep(201, patientId);
			else
				return JSONMessageResponse.generateMessageRep(500, "Patient not created");
	}
	
	/**
	 * Handles DELETE requests; removes a Patient resource from the database at {patientId}
	 *
	 * @returns JSONMessageResponse with details on success/failure.
	 * @see aperturescience.types.JSONMessageResponse
	 */
	@Delete
	public JsonRepresentation deletePatient()
	throws IOException {
		DatabaseResource db = new DatabaseResource(WarGamesApplication.couchdburl, WarGamesApplication.databasename);
		if ( db.deletePatient(patientId) )
			return JSONMessageResponse.generateMessageRep(200, "Patient[" + patientId + "] deleted.");
		else
			return JSONMessageResponse.generateMessageRep(404, "Patient[" + patientId + "] not found.");
	}
}
